package com.huangpeng.algorithm;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author huangpeng
 * @Title 算法测试类
 * @Package
 * @Date 2021/6/28 15:22
 * @Description
 * @Version 1.0
 */
public class algorithmRudimentsTest {
    /**
     * 找出一个数组中一个数字出现次数最多的数字
     * 用HashMap的key来存放数组中存在的数字，value存放该数字在数组中出现的次数
     * @author hp
     */
    @org.junit.Test
    public void test1(){
        int[] array = {2, 1, 2, 3, 4, 5, 2, 2, 2, 2};
        //map的key存放数组中存在的数字，value存放该数字在数组中出现的次数
        HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
        for(int i = 0; i < array.length; i ++){
            if(map.containsKey(array[i])){
                int temp = map.get(array[i]);
                map.put(array[i],temp + 1);
            }else{
                map.put(array[i],1);
            }
        }

        Collection<Integer> count = map.values();
        //找出map的value中最大的数字，也就是数组中数字出现最多的次数
        int maxCount = Collections.max(count);
        int maxNumber = 0;

        for(Map.Entry<Integer, Integer> entry : map.entrySet()){
            //得到value为maxCount的key，也就是数组中出现次数最多的数字
            if(maxCount == entry.getValue()){
                maxNumber = entry.getKey();
            }
        }

        System.out.println("出现次数最多的数字为：" + maxNumber + "该数字一共出现" + maxCount + "次");
    }

    /**
     * 给定一个字符串数组lines, 每一个元素代表一个IP地址，找到出现频率最高的IP。
     * @author hp
     */
    @org.junit.Test
    public void test2(){
        String[] ipLines = {"192.168.1.1","192.118.2.1","192.168.1.1"};
        //map的key存放数组中存在的数字，value存放该数字在数组中出现的次数
        HashMap<String,Integer> map = new HashMap<>();
        for (String ip : ipLines) {
            map.put(ip,map.getOrDefault(ip,0) + 1);
        }
        //找出map中出现次数最多的ip的key和value
        Map.Entry<String,Integer> maxValueEntry = Collections.max(map.entrySet(), Comparator.comparing(Map.Entry::getValue));
        //取出出现次数最多的map的key
        System.out.println(maxValueEntry.getKey());
    }

    /**
     * 给你一个大小size,生成一个元素从1 到 size的数组
     * @author hp
     */
    @org.junit.Test
    public void test3(){
        int size = 10;
        List<Integer> list = new ArrayList<>();
        for (int i = 1; i < size + 1; i++) {
            list.add(i);
        }
        System.out.println(list);
    }

    /**
     * 给你一个数组和两个索引，交换下标为这两个索引的数字
     * @author hp
     */
    @org.junit.Test
    public void test4(){
        int[] a = {1, 2, 3, 4};
        System.out.println(Arrays.toString(a));
        int index1 = 1;
        int index2 = 3;
        //使用异或运算交换位置
        a[index1] = a[index1]^a[index2];
        a[index2] = a[index1]^a[index2];
        a[index1] = a[index1]^a[index2];

        System.out.println(Arrays.toString(a));
    }

    /**
     * 有偶数个数相同，需要找出不同的那个数时，比如：2，3，4，4，3，5，5，6，6，7，7
     * @author hp
     */
    @org.junit.Test
    public void test5(){
        int array[] = {2,3,4,4,3,5,5,6,6,7,7};
        int a = 0;
        for (int i = 0; i < array.length; i++) {
            a^= array[i];
        }
        System.out.println(a);
    }

    /**
     * 将一个链表转换为一个数组。
     * @author hp
     */
    @org.junit.Test
    public void test6(){
        /*List<Integer> r = new ArrayList<>();
        while(head != null){
            r.add(head.val);
            head = head.next;
        }*/
    }

    /**
     * 给出两个整数 aa 和 bb , 求他们的和并以整数（int）的形式返回。
     * @author hp
     */
    @org.junit.Test
    public void test7(){
        // 主要利用异或运算来完成
        // 异或运算有一个别名叫做：不进位加法
        // 那么a ^ b就是a和b相加之后，该进位的地方不进位的结果
        // 然后下面考虑哪些地方要进位，自然是a和b里都是1的地方
        // a & b就是a和b里都是1的那些位置，a & b << 1 就是进位
        // 之后的结果。所以：a + b = (a ^ b) + (a & b << 1)
        // 令a' = a ^ b, b' = (a & b) << 1
        // 可以知道，这个过程是在模拟加法的运算过程，进位不可能
        // 一直持续，所以b最终会变为0。因此重复做上述操作就可以
        // 求得a + b的值。
        int a = 1;
        int b = 29;
        while (b != 0){
            int _a = a^b;
            int _b = (a & b) << 1;
            a = _a;
            b = _b;
        }
        System.out.println(a);
    }
}
